import failedImage from '@/assets/js/failedImage';
import loadingImage from '@/assets/js/loadingImage';

const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // ios终端
const isRtl = () => ['ar', 'ur'].includes(sessionStorage?.getItem('language'));
const lang = () =>
    ['en', 'ar', 'ur', 'tr', 'in'].includes(sessionStorage.getItem('language'))
        ? sessionStorage.getItem('language')
        : 'en';
let isSupportWebp = false;
const checkWebpSupport = () => {
    const img = new Image();
    img.onload = () => {
        isSupportWebp = img.width > 0 && img.height > 0;
    };
    img.onerror = () => {
        isSupportWebp = false;
    };
    img.src = ``;
};
checkWebpSupport();

const isLocalNetwork =
    window.location.host.includes('192.168.') || window.location.host.includes('localhost');

/**
 * 如果当前语言是反向布局，追加direction: rtl;
 * 使用方式: <div v-rtl />
 */
const rtl = {
    beforeMount(el) {
        isRtl() && (el.style.direction = 'rtl');
    },
};

/**
 * 固定当前direction为ltr;
 * 使用方式: <div v-ltr />
 */
const ltr = {
    beforeMount(el) {
        el.style.direction = 'ltr';
    },
};

/**
 * 如果当前语言是反向布局，追加一个类名;
 * 使用方式: <div v-rtl-class="'rtl'" />
 */
const rtlClass = {
    beforeMount(el, binding) {
        isRtl() && el.classList.add(binding?.value || 'rtl');
    },
};

/**
 * 加入文本单行溢出隐藏样式，同时将direction固定为ltr，传入的数值将作为max-width使用
 * 使用方式: <div v-ellipsis="300" />
 */
const ellipsis = {
    beforeMount(el, binding) {
        el.classList.add('text-ellipsis');
        el.style.textOverflow = 'ellipsis';
        el.style.whiteSpace = 'nowrap';
        el.style.overflow = 'hidden';
        el.style.direction = 'ltr';
        if (binding.value) {
            el.style.maxWidth = `${binding.value / 75}rem`;
        }
    },
};

/**
 * 适用于img标签的指令，导入以/assets/images目录为根目录的图片，如果支持webp格式会优先选择webp。传入参数中的*号替换成当前语言(en、ar、ur、tr)
 *  使用方式: < img v-src="'summerDay/banner.jpg'" />"
 *  多语言: < img v-src="'summerDay/banner-*.jpg'" />"
 */
const lazyLoadImg = (el, src) => {
    const io = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting) {
            el.src = src;
            io.disconnect();
        }
    });
    io.observe(el);
};
const src = {
    beforeMount(el, binding) {
        const targetFileSrc = new URL(
            `../assets/images/${binding?.value?.replaceAll('*', lang())}`,
            import.meta.url?.replace('app.kumiamei', 'activity.kumiamei.com')
        )?.href;
        if (
            typeof binding?.value === 'string' &&
            (binding?.value?.startsWith('http://') || binding?.value?.startsWith('https://'))
        ) {
            el.src = binding?.value?.replaceAll('*', lang());
            return;
        }
        if (isLocalNetwork) {
            el.src = targetFileSrc;
            return;
        }
        const webpFileName = targetFileSrc?.replace(/(.jpg)|(.jpeg)|(.png)$/i, '.webp');
        const s = isSupportWebp ? webpFileName : targetFileSrc;
        el.onerror = () => {
            if (el.src === targetFileSrc) {
                el.src = failedImage;
                el.onerror = null;
            } else {
                el.src = targetFileSrc;
            }
        };
        if (s) {
            if (binding?.arg === 'lazy') {
                el.src = loadingImage;
                el._src = s;
            } else {
                el.src = s;
            }
        }
    },
    mounted(el, binding) {
        if (!isLocalNetwork && binding?.arg === 'lazy') {
            lazyLoadImg(el, el._src);
        }
    },
    beforeUpdate(el, binding) {
        if (binding.value !== binding.oldValue) {
            src.beforeMount(el, binding);
        }
    },
};

/**
 * 跟src指令功能一致，不过这个指令更改的是元素的background属性，适用于div标签，如果支持webp格式会优先选择webp。传入参数中的*号替换成当前语言(en、ar、ur、tr)
 * 默认的对齐方式center，大小100%, 如果需要更改，可以传入数组参数['banner.jpg', 'X轴对齐方式', 'Y轴对齐方式', '宽度', '高度']
 * 使用方式: <div v-bg="'summerDay/banner.jpg'" />"
 * 多语言: <div v-bg="'summerDay/banner-*.jpg'" />"
 * 手动指定对齐方式和宽高: <div v-bg="['summerDay/banner.jpg', 'left', 'top', '300px', '150px']" />
 */
const bg = {
    beforeMount(el, binding) {
        const setBackground = (url) => {
            if (!url) return;
            if (typeof binding?.value === 'string') {
                el.style.background = `url('${url}') center center / 100% 100% no-repeat`;
            } else if (Array.isArray(binding?.value)) {
                el.style.background = `url('${url}') ${binding.value?.[1] || 'center'} ${
                    binding.value?.[2] || 'center'
                } / ${binding.value?.[3] || '100%'} ${binding.value?.[4] || '100%'} no-repeat`;
            }
        };
        if (
            typeof binding?.value === 'string' &&
            (binding?.value?.startsWith('http://') || binding?.value?.startsWith('https://'))
        ) {
            el.style.background = binding?.value?.replaceAll('*', lang());
            return;
        }
        let url;
        if (typeof binding?.value === 'string') {
            url = binding.value.replaceAll('*', lang());
        } else if (Array.isArray(binding?.value)) {
            url = binding.value?.[0]?.replaceAll('*', lang());
        }
        const targetFileSrc = new URL(
            `../assets/images/${url}`,
            import.meta.url?.replace('app.kumiamei', 'activity.kumiamei.com')
        )?.href;
        if (isLocalNetwork) {
            setBackground(targetFileSrc);
            return;
        }
        const webpFileName = targetFileSrc?.replace(/(.jpg)|(.jpeg)|(.png)$/i, '.webp');
        if (isSupportWebp) {
            setBackground(webpFileName);
            // const req = new XMLHttpRequest();
            // req.open('GET', webpFileName);
            // req.send();
            // req.onreadystatechange = () => {
            //     if (req.status === 404) {
            //         setBackground(targetFileSrc);
            //     }
            //     req.onreadystatechange = null;
            //     req.abort();
            // };
        } else {
            setBackground(targetFileSrc);
        }
    },
    beforeUpdate(el, binding) {
        if (binding.value !== binding.oldValue) {
            bg.beforeMount(el, binding);
        }
    },
};

/**
 * 当元素出现在画面中，追加一个类名, 可以用于实现出场动画。
 * (不传入类名时，默认追加类名flipAnimation, 全局已定义该动画，可直接使用)
 * 如果需要追加多个类名，可以传入数组
 * 使用方式: <div v-entry-class="类名" />
 * 多个类名: <div v-entry-class="[类名1, 类名2]" />
 */
const entryClass = {
    beforeMount(el, binding) {
        const io = new IntersectionObserver((entries) => {
            if (entries[0].isIntersecting) {
                if (typeof binding?.value === 'string') {
                    el.classList.add(binding.value);
                } else if (Array.isArray(binding?.value)) {
                    binding.value.forEach((v) => {
                        if (typeof v === 'string') {
                            el.classList.add(v);
                        }
                    });
                } else {
                    el.classList.add('flipAnimation');
                }
                io.disconnect();
            }
        });
        io.observe(el);
    },
};

/**
 * 追加animationDelay属性
 * 使用方式: <div v-animation-delay="2" />
 */
const animationDelay = {
    beforeMount(el, binding) {
        el.style.animationDelay = `${binding.value}s`;
    },
};

/**
 * 点击元素自身外部时，触发回调函数，可用于实现点击空白处隐藏菜单或提示的逻辑
 * 使用方式：<div v-click-outside="handleClose"/>
 */
const clickOutside = {
    beforeMount(el, binding) {
        el.__clickOutsideFn = (e) => {
            !el.contains(e.target) && typeof binding?.value === 'function' && binding.value();
        };
        document.addEventListener('click', el.__clickOutsideFn);
    },
    beforeUnmount(el) {
        document.removeEventListener('click', el.__clickOutsideFn);
    },
};

/**
 * 监听长按事件, 默认触发长按事件为300ms，如果需要更改触发时间，可以传入一个参数，参数值为需要长按的毫秒值
 * 使用方式: <div v-long-touch="handleLongTouch"></div>
 * 自定义长按时长: <div v-long-touch:500="handleLongTouch"></div>
 */
export const longTouch = {
    beforeMount(el, binding) {
        el.__handleTouchStart = (e) => {
            e.preventDefault();
            el.__longTouchTimer = setTimeout(
                () => {
                    el.__longTouchTimer && clearTimeout(el.__longTouchTimer);
                    el.__longTouchTimer = null;
                    // 判定为长按
                    typeof binding?.value === 'function' && binding.value();
                },
                binding?.arg ? +binding.arg : 300
            );
        };
        el.__handleTouchEnd = (e) => {
            e.preventDefault();
            if (el.__longTouchTimer) {
                clearTimeout(el.__longTouchTimer);
                el.__longTouchTimer = null;
                // 判定为短按, 预留逻辑
            }
        };
        el.addEventListener('touchstart', el.__handleTouchStart, { passive: false });
        el.addEventListener('touchend', el.__handleTouchEnd);
    },
    beforeUnmount(el) {
        el.removeEventListener('touchstart', el.__handleTouchStart);
        el.removeEventListener('touchend', el.__handleTouchEnd);
    },
};

/**
 * 用于input框的自动聚焦
 * 使用方式：<input v-focus />
 */
const focus = {
    mounted(el) {
        el?.focus();
    },
};

/**
 * IOS设备切换到乌尔都语时可能会出现字体变得巨大的问题。使用此自定义指令，可以将字体缩小到css设定大小的60%。只需要在页面父元素调用一次即可。
 */
const zoomedMap = new WeakMap();
const setFontSizeZoom = (el) => {
    if (zoomedMap.has(el)) {
        el.style.fontSize = `${zoomedMap.get(el) * 0.6}px`;
    } else {
        const px = +getComputedStyle(el).fontSize.replaceAll('px', '');
        zoomedMap.set(el, px);
        el.style.fontSize = `${px * 0.6}px`;
    }
};
const traversalChildrenDOM = (el) => {
    for (let i = 0; i < el.children.length; i++) {
        if (!el?.__notZoom) {
            traversalChildrenDOM(el.children[i]);
        }
    }
    if (el.textContent && !el?.__notZoom) {
        setFontSizeZoom(el);
    }
};
const urf = {
    beforeMount(el) {
        if (!isiOS || window.sessionStorage.getItem('language') !== 'ur') return;
        el.__mo = new MutationObserver(() => {
            if (el.__moTimer) clearTimeout(el.__moTimer);
            el.__moTimer = setTimeout(() => {
                traversalChildrenDOM(el);
            }, 4);
        });
        el.__mo.observe(el, {
            childList: true,
            subtree: true,
        });
    },
    beforeUnmount(el) {
        clearTimeout(el.__moTimer);
        el.__mo.disconnect();
    },
};
const urfIgnore = {
    beforeMount(el) {
        el.__notZoom = true;
    },
};

/**
 * 增加当前客户端语言的类名
 */
const langClass = {
    beforeMount(el) {
        el.classList.add(lang());
        el.lang = lang();
    },
};

/**
 * 反向布局才显示该元素
 */
const showRtl = {
    beforeMount(el) {
        if (!isRtl()) {
            el.style.display = 'none';
        }
    },
};

/**
 * 正向布局才显示该元素
 */
const showLtr = {
    beforeMount(el) {
        if (isRtl()) {
            el.style.display = 'none';
        }
    },
};

export default {
    rtl,
    ltr,
    rtlClass,
    ellipsis,
    src,
    bg,
    entryClass,
    animationDelay,
    clickOutside,
    longTouch,
    focus,
    urf,
    langClass,
    showRtl,
    showLtr,
    urfIgnore,
};
